//TreeLoader2: Electric Boogaloo

package search.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import primitives.cluster.ClusterHead;
import primitives.graph.Graph;
import primitives.graph.Node;
import translator.DOTWriter;
import gpinterpreter.*;

//foo bar baz

abstract class TreeLoader2 {

	def static definitionLine = ~/\W*(.+?)\W*\[.*\]/;
	
	/*
	 						    +-------------------------------------------------------- Opening whitespace                
	 						    | 	
	 						    |   +---------------------------------------------------- Open quote for start node if any+ GROUP 1
	 						    |   |    																				  |
	 						    |   |   +------------------------------------------------ Name of first node  			  | GROUP 2 <- 
	 						    |   |   |																				  |
	 						    |   |   |    +------------------------------------------- Closing quote of first node name+ 
	 						    |   |   |    | 
	 						    |   |   |    | +----------------------------------------- Whitespace if any
	 						    |   |   |    | |
	 						    |   |   |    | |    +------------------------------------ Whitespace if any
	 						    |   |   |    | |    |        
	 						    |   |   |    | |    |   +-------------------------------- Open quote for destination node + GROUP 3    
	 						    |   |   |    | |    |   |    															  |
	 						    |   |   |    | |    |   |   +---------------------------- Name of destination node        | GROUP 4 <- 
	 						    |   |   |    | |    |   |   |  															  |
	 						    |   |   |    | |    |   |   |  +------------------------- " or nothing (depends on 3) ----+
	 						    |   |   |    | |    |   |   |  |  
	 						    |   |   |    | |    |   |   |  | +----------------------- Whitespace if any  
	 						    |   |   |    | |    |   |   |  | |  
	 						    |   |   |    | |    |   |   |  | |  +-------------------- [Option block] <0 or 1 times>	    GROUP 5					
	 						    |   |   |    | |    |   |   |  | |  |
	*///						    |   |   |    | |    |   |   |  | |  |   +---------------- Options                           GROUP 6 <-
	def static transitionLine =   ~/\s*("?)(.+)\1\s*->\s*("?)([^\[]+)\3\s*(\[(.*)\])?/;
	
	static final FIRST_NODE = 2;
	static final SECOND_NODE = 4;
	static final OPTIONS = 6;

    def static ClusterHead loadTreeFromDot(File input) throws IOException{
            String line;
			ArrayList<String> lines = new ArrayList<String>();
			return loadTreeFromDot((String[])(input.readLines().toArray()))
		}
	
	def static ClusterHead loadTreeFromSerial(String filename) throws IOException{
		return loadTreeFromSerial(new File(filename));
	}
	def static ClusterHead loadTreeFromSerial(File file) throws IOException{
		ObjectInputStream ois;
		ois = new ObjectInputStream(new FileInputStream(file));
		// Deserialize the object
		ClusterHead ret  = (ClusterHead) ois.readObject();
		ois.close();
		return ret;
	}

	public static ClusterHead loadTreeFromDotS(String input) {
		String[] lines = input.split("\r\n|\r|\n");
		return loadTreeFromDot(lines);
	}

	public static ClusterHead loadTreeFromDot(String[] lines){
		HashMap<String, Node> nodes = new HashMap<String, Node>();
		Graph g = new Graph();
		
		lines.findAll{!(it =~  /^\W*#.*$/)}.each{ line ->
			Matcher m = definitionLine.matcher(line);
			
			if (m.matches()) {
				

				
				Matcher m2 = transitionLine.matcher(line);
				if (m2.matches()) {
					String s1 = m2.group(FIRST_NODE);
					String s2 = m2.group(SECOND_NODE);
					s1 = s1.trim();
					s2 = s2.trim();
					// String s3 = m2.group(3);
					nodes.put(s1, new Node(s1));
					nodes.put(s2, new Node(s2));
				} else {
					String s1 = m.group(1);
					s1 = s1.trim();
					nodes.put(s1, new Node(s1));
				}
			}
		}

		for (String k : nodes.keySet()) {
			g.addNode(nodes.get(k));
		}

		lines.findAll{!(it =~  /^\W*#.*$/)}.each{ line ->
			Matcher m2 = transitionLine.matcher(line);
			if (m2.matches()) {
				String s1 = m2.group(FIRST_NODE).trim();
				String s2 = m2.group(SECOND_NODE).trim();
				String s3 = m2.group(OPTIONS)
				
				if (s3 == null)
					s3 = "";
				else
					s3 = s3.trim();
                 s3 = s3.replace("[", "");
                 s3 = s3.replace("];", "");
                 s3 = s3.replace("]","");
                 s3 = s3.replace("[]","");
				try{
					nodes.get(s1).connect(nodes.get(s2), s3);
				}catch(NullPointerException e){
					println "Caught a NullPointerException when trying to connect $s1 to $s2"
					println "Node listing:"
					nodes.each{
						name,node->
						println "	*$name"
					}
				}
			}
		}
		
		def found = false;


		return new ClusterHead(g);
	}
	public static ClusterHead loadTreeFromDot(String filename)
			throws IOException {
		
                        return loadTreeFromDot(new File(filename));
		
		

	}
}
